﻿using System;
using System.Diagnostics;
using Microsoft.Practices.ObjectBuilder;

namespace Microsoft.Practices.CompositeUI.Instrumentation
{
    /// <summary>
    /// 	Indicates that a property or parameter will be dependency injected with a <see cref = "TraceSource" />.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
    public class TraceSourceAttribute : ParameterAttribute
    {
        #region Fields & Properties

        private readonly string _sourceName;

        /// <summary>
        /// 	Name of the <see cref = "TraceSource" /> to get.
        /// </summary>
        public string SourceName
        {
            get
            {
                return _sourceName;
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// 	Creates a new instance of the <see cref = "TraceSourceAttribute" /> class.
        /// </summary>
        /// <param name = "sourceName">Name of the <see cref = "TraceSource" /> to get.</param>
        public TraceSourceAttribute(string sourceName)
        {
            _sourceName = sourceName;
        }

        #endregion

        #region Overrides of ParameterAttribute

        /// <summary>
        /// 	See <see cref = "ParameterAttribute.CreateParameter" /> for more information.
        /// </summary>
        public override IParameter CreateParameter(Type memberType)
        {
            return new TraceSourceParameter(memberType, _sourceName);
        }

        #endregion

        #region TraceSourceParameter Class

        private class TraceSourceParameter : KnownTypeParameter
        {
            private readonly string _sourceName;

            public TraceSourceParameter(Type memberType, string sourceName) : base(memberType)
            {
                _sourceName = sourceName;
            }

            public override object GetValue(IBuilderContext context)
            {
                var key = new DependencyResolutionLocatorKey(typeof (ITraceSourceCatalogService), null);
                var service = (ITraceSourceCatalogService) context.Locator.Get(key);
                return service != null ? service.GetTraceSource(_sourceName) : null;
            }
        }

        #endregion
    }
}